package com.xiaoyy.core.config.aspect;

import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.xiaoyy.core.common.vo.BasePageVO;
import com.xiaoyy.core.common.vo.BaseVO;
import com.xiaoyy.core.config.util.ServiceRequestUtil;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 服务请求拦截
 *
 * @author chenzh
 * @date 2018-08-15
 */
@Aspect
@Component
public class ServiceRequestAspect {
    private static final Logger logger = LoggerFactory.getLogger(ServiceRequestAspect.class);

    @Pointcut("execution(public * com.xiaoyy..*.gateway.controller..*.*(..))")
    private void allControllerMethod() {
    }

    @Around("allControllerMethod()")
    public Object doAround(ProceedingJoinPoint call) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //获取目标对象对应的类名
        String className = call.getTarget().getClass().getName();
        // 获取目标对象上正在执行的方法名
        String methodName = call.getSignature().getName();
        String ip = ServletUtil.getClientIP(request);
        //路由id
        String routerId=request.getHeader("routerId");
        Object[] arguments = call.getArgs();
        logger.info("开始执行:" + className + "." + methodName + "()方法...");
        String acccessToken = ServiceRequestUtil.getAccessToken(request, response);
        for (int i = 0; i < arguments.length; i++) {
            Object obj = arguments[i];
            if (obj instanceof ServletRequest || obj instanceof ServletResponse || obj instanceof MultipartFile) {
                //ServletRequest不能序列化，从入参里排除，否则报异常：java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
                //ServletResponse不能序列化 从入参里排除，否则报异常：java.lang.IllegalStateException: getOutputStream() has already been called for this response
                continue;
            }
            logger.info("请求信息"+i+":" + JSON.toJSONString(obj));
            if (obj instanceof BaseVO) {
                BaseVO baseReq = (BaseVO) obj;
                baseReq.setAccessToken(acccessToken);
                baseReq.setOpRouterId(routerId);
                baseReq.setReqIp(ip);
                break;
            }else if (obj instanceof BasePageVO) {
                BasePageVO baseReq = (BasePageVO) obj;
                baseReq.setAccessToken(acccessToken);
                baseReq.setOpRouterId(routerId);
                baseReq.setReqIp(ip);
                break;
            }
        }
        Object object = call.proceed();
        if (object!=null){
            logger.info("返回信息:" + JSON.toJSONString(object));
        }
        return object;
    }
}
